package com.yilin.tms.order.service.clearing.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.DateTimeUtil;
import com.yilin.commons.util.MathUtil;
import com.yilin.commons.util.StringUtil;
import com.yilin.tms.core.commons.utils.OrderUtil;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.commons.utils.QueryUtil;
import com.yilin.tms.core.entity.order.clearing.ClearingDetail;
import com.yilin.tms.core.entity.order.goods.GoodsOrder;
import com.yilin.tms.core.entity.order.payment.OrderPaymentCost;
import com.yilin.tms.core.entity.order.payment.ServicePaymentCost;
import com.yilin.tms.core.entity.order.rob.RobOrder;
import com.yilin.tms.core.entity.order.transit.TransitOrder;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.order.mapper.clearing.ClearingDetailMapper;
import com.yilin.tms.order.mapper.rob.RobOrderMapper;
import com.yilin.tms.order.mapper.transit.TransitOrderMapper;
import com.yilin.tms.order.service.clearing.IClearingService;
import com.yilin.tms.order.service.payment.ICalculationService;
import com.yilin.tms.order.service.payment.IOrderPaymentCostService;
import com.yilin.tms.order.service.payment.IOrderSettlementCostService;
import com.yilin.tms.order.service.payment.IServicePaymentCostService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;

@Service
@Transactional(rollbackOn = Exception.class)
public class ClearingService extends ServiceImpl<ClearingDetailMapper, ClearingDetail> implements IClearingService {

    @Resource
    private RobOrderMapper robOrderMapper;
    @Resource
    private TransitOrderMapper transitOrderMapper;
    @Resource
    private ClearingDetailMapper clearingDetailMapper;
    @Resource
    private IOrderPaymentCostService paymentCostService;
    @Resource
    private IOrderSettlementCostService settlementCostService;
    @Resource
    private IServicePaymentCostService servicePaymentCostService;
    @Resource
    private ICalculationService calculationService;

    @Override
    public PageData<ClearingDetail> getClearingDetailPage(Account loginUser, ClearingDetail query, Integer page, Integer limit) {
        QueryWrapper<ClearingDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plat_id", loginUser.getOrganizeId());
        return clearingDetailMapper.selectPage(new PageData<>(page, limit), QueryUtil.andQueryWrapper(queryWrapper, query));
    }

    /**
     * 确认回执后创建清算单
     */
    @Override
    public ClearingDetail createClearingDetail(TransitOrder transitOrder) {
        ClearingDetail clearingDetail = getClearingDetailByTransitOrderId(transitOrder.getId());
        if (clearingDetail != null) return clearingDetail;
        clearingDetail = new ClearingDetail();
        clearingDetail.setClearingOrderNo(DateTimeUtil.dateNo("CL"));
        clearingDetail.setClearingStatus(ClearingDetail.ClearingStatus.going);
        clearingDetail.setClearingType(ClearingDetail.ClearingType.auto);
        if (transitOrder.getHandLiquidation()) clearingDetail.setClearingType(ClearingDetail.ClearingType.manual);
        //平台信息
//        clearingDetail.setPlatId(transitOrder.getPlatId());
//        clearingDetail.setPlatName(transitOrder.getPlatName());
//        clearingDetail.setZonePlatId(transitOrder.getZonePlatId());
//        clearingDetail.setZonePlatName(transitOrder.getZonePlatName());
        //订单数据
        clearingDetail.setTransitOrderId(transitOrder.getId());
        clearingDetail.setTransitOrderNo(transitOrder.getTransportNo());
        clearingDetail.setGatherRecordId(null);
        clearingDetail.setGatherRecordNo(null);
        clearingDetail.setMatchmaking(transitOrder.getMatching());
        clearingDetail.setIncludedTax(transitOrder.getIncludedTax());
        //货主信息
        clearingDetail.setShipperOrganizeId(transitOrder.getShipperOrganizeId());
        clearingDetail.setShipperOrganizeName(transitOrder.getShipperOrganizeName());
        clearingDetail.setShipperAccountId(transitOrder.getShipperAccountId());
        clearingDetail.setShipperAccountName(transitOrder.getShipperAccountName());
        //车主信息
        clearingDetail.setRobOrganizeId(transitOrder.getRobOrganizeId());
        clearingDetail.setRobOrganizeName(transitOrder.getRobOrganizeName());
        clearingDetail.setRobAccountId(transitOrder.getRobAccountId());
        clearingDetail.setRobAccountName(transitOrder.getRobAccountName());
        //---------------------------------------------------------------------
        clearingDetail.setActualSettlementType(transitOrder.getSettlementType());
        //费率---货主
        OrderPaymentCost paymentCost = paymentCostService.getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.receipt);
        if (paymentCost==null) paymentCost =  paymentCostService.generateReceiptOrderPayment(transitOrder);
        clearingDetail.setShipperFeeRate(paymentCost.getShipperFeeRate());
        clearingDetail.setShipperTaxRate(paymentCost.getShipperTaxRate());
        clearingDetail.setInsuranceRate(paymentCost.getInsuranceRate());
        //费率---车主
        RobOrder robOrder = robOrderMapper.selectById(transitOrder.getRobOrderId());
        clearingDetail.setTruckerFeeRate(robOrder.getTruckerFeeRate());
        clearingDetail.setAddedTaxRate(robOrder.getAddedTaxRate());
        clearingDetail.setCityTaxRate(robOrder.getCityTaxRate());
        clearingDetail.setLocalEduTaxRate(robOrder.getLocalEduTaxRate());
        clearingDetail.setEduAddTaxRate(robOrder.getEduAddTaxRate());
        clearingDetail.setIncomeTaxRate(robOrder.getIncomeTaxRate());
        //固定费用---车主
        clearingDetail.setDiffIndemnityCost(transitOrder.getDiffIndemnityCost());
        clearingDetail.setDiffIndemnityDetail(transitOrder.getDiffIndemnityDetail());
        clearingDetail.setOilCost(transitOrder.getOilCost());
        clearingDetail.setEtcTollCost(transitOrder.getEtcTollCost());
        //-运输费
        clearingDetail.setShipperTransportCost(OrderUtil.getTransCostBySettleType(clearingDetail.getActualSettlementType(), transitOrder));
        //设置新的各项费用
        setClearingDetailCost(clearingDetail);
        clearingDetailMapper.insert(clearingDetail);
        return clearingDetail;
    }

    /**
     * 锁定/取消锁定 清算
     */
    @Override
    public void lockClearingDetail(Account loginUser, String detailId, ClearingDetail.LockStatus lockStatus) {
        ClearingDetail clearingDetail = clearingDetailMapper.selectById(detailId);
        if (clearingDetail == null) throw new BusinessException("清算记录不存在");
        if (StringUtil.isNotEmpty(clearingDetail.getOptAccountId()) && !loginUser.getId().equals(clearingDetail.getOptAccountId())) {
            throw new BusinessException("该条记录已被其他用户锁定！");
        }
        clearingDetail.setLockStatus(lockStatus);
        clearingDetail.setOptAccountId(lockStatus == ClearingDetail.LockStatus.lock ? loginUser.getId() : "");
        clearingDetail.setOptAccountName(lockStatus == ClearingDetail.LockStatus.lock ? loginUser.getName() : "");
        clearingDetail.setLockTime(lockStatus == ClearingDetail.LockStatus.lock ? new Date() : null);
        updateById(clearingDetail);
    }

    /**
     * 手动清算更新
     */
    @Override
    public void updateClearingDetail(Account loginUser, TransitOrder transitOrder, ClearingDetail fromDetail) {
        ClearingDetail clearingDetail = clearingDetailMapper.selectById(fromDetail.getId());
        if (clearingDetail == null) throw new BusinessException("原始清算记录不存在");
        if (clearingDetail.getClearingStatus() == ClearingDetail.ClearingStatus.scrap) throw new BusinessException("清算已作废");
        if (clearingDetail.getClearingStatus() == ClearingDetail.ClearingStatus.success) throw new BusinessException("清算已完成");
        if (clearingDetail.getOptAccountId() == null) throw new BusinessException("请先锁定记录");
        if (!clearingDetail.getOptAccountId().equals(loginUser.getId())) throw new BusinessException("该记录正在被其他人操作");
        clearingDetail.setActualSettlementType(fromDetail.getActualSettlementType());
        //费率---货主
        clearingDetail.setShipperFeeRate(fromDetail.getShipperFeeRate());
        clearingDetail.setShipperTaxRate(fromDetail.getShipperTaxRate());
        clearingDetail.setInsuranceRate(fromDetail.getInsuranceRate());
        //费率---车主
        clearingDetail.setTruckerFeeRate(fromDetail.getTruckerFeeRate());
        clearingDetail.setAddedTaxRate(fromDetail.getAddedTaxRate());
        clearingDetail.setCityTaxRate(fromDetail.getCityTaxRate());
        clearingDetail.setLocalEduTaxRate(fromDetail.getLocalEduTaxRate());
        clearingDetail.setEduAddTaxRate(fromDetail.getEduAddTaxRate());
        clearingDetail.setIncomeTaxRate(fromDetail.getIncomeTaxRate());
        //----固定费用
        clearingDetail.setAdditionalCost(fromDetail.getAdditionalCost());//固定费用
        clearingDetail.setInsuranceCost(fromDetail.getInsuranceCost());//固定费用
        clearingDetail.setAlreadyPayCost(fromDetail.getAlreadyPayCost());//已支付
        //----固定费用
        clearingDetail.setDiffIndemnityCost(fromDetail.getDiffIndemnityCost());
        if (!fromDetail.getDiffIndemnityCost().equals(transitOrder.getDiffIndemnityCost())) {
            clearingDetail.setDiffIndemnityDetail(String.format("%s;清算修改:%s元",clearingDetail.getDiffIndemnityDetail(),fromDetail.getDiffIndemnityCost()));
        }
        clearingDetail.setOilCost(fromDetail.getOilCost());
        clearingDetail.setEtcTollCost(fromDetail.getEtcTollCost());
        //-运输费
        if (transitOrder.getSettlementType()==GoodsOrder.SettlementType.gatherTotal ){
            if(clearingDetail.getActualSettlementType()!= GoodsOrder.SettlementType.gatherTotal) {
                throw new BusinessException("运单汇总计价，清算暂不支持切换其他结算方式！请按汇总量结算！");
            }
            if(transitOrder.getGatherTransportCost()==0) throw new BusinessException("运单汇总费用为0，请先完成汇总");
        }
        clearingDetail.setShipperTransportCost(OrderUtil.getTransCostBySettleType(clearingDetail.getActualSettlementType(), transitOrder));
        //设置新的各项费用
        setClearingDetailCost(clearingDetail);
        clearingDetailMapper.updateById(clearingDetail);
    }

    /**
     * 确认清算
     */
    @Override
    public void sureClearingDetail(Account loginUser, TransitOrder transitOrder, ClearingDetail clearingDetail) {
        if (clearingDetail == null) throw new BusinessException("没有找到清算记录");
        if (clearingDetail.getShipperTransportCost() == 0) throw new BusinessException("货主运费为空，请先完成汇总");
        if (clearingDetail.getClearingStatus() == ClearingDetail.ClearingStatus.success) throw new BusinessException("清算已完成");
        if (clearingDetail.getClearingStatus() == ClearingDetail.ClearingStatus.scrap) throw new BusinessException("清算已作废");
        if (clearingDetail.getOptAccountId() == null) throw new BusinessException("请先锁定记录");
        if (!clearingDetail.getOptAccountId().equals(loginUser.getId())) throw new BusinessException("该记录正在被其他人操作");
        clearingDetail.setOptTime(new Date());
        clearingDetail.setClearingStatus(ClearingDetail.ClearingStatus.success);

        //容错
        OrderPaymentCost orderPaymentCost = paymentCostService.getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.delivery);
        if (orderPaymentCost==null){
            RobOrder robOrder = robOrderMapper.selectById(transitOrder.getRobOrderId());
            paymentCostService.generateDeliveryOrderPayment(transitOrder,robOrder);
        }
        OrderPaymentCost orderPaymentCost2 = paymentCostService.getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.receipt);
        if (orderPaymentCost2==null){
            paymentCostService.generateReceiptOrderPayment(transitOrder);
        }


        //自动生成清算预支付单
        paymentCostService.generateClearingOrderPayment(transitOrder, clearingDetail);
        //生成网货 > 运营服务费 孵化平台费用单
        servicePaymentCostService.generateServicePayment(ServicePaymentCost.ServicePlatType.whPlat, clearingDetail);
        //生成孵化 > 运营服务费 易林平台费用单
        servicePaymentCostService.generateServicePayment(ServicePaymentCost.ServicePlatType.fhPlat, clearingDetail);
        //生成平台 > 司机结算单
        settlementCostService.generateOrderSettlement(transitOrder, clearingDetail);
        //-----------------------------------------------------------------------------------
        clearingDetailMapper.updateById(clearingDetail);
        //更新运单--完成
        transitOrder.setClearingDetailId(clearingDetail.getId());
        transitOrder.setClearCompleteTime(new Date());
        transitOrder.setShipperActualPayCost(clearingDetail.getShipperActualPayCost());
        transitOrder.setTruckerActualIncomeCost(clearingDetail.getTruckerActualIncomeCost());
        transitOrder.setTransitStatus(TransitOrder.TransitStatus.complete);
        transitOrderMapper.updateById(transitOrder);
    }

    /**
     * 找查：订单ID获取清算单
     */
    @Override
    public ClearingDetail getClearingDetailByTransitOrderId(String transitOrderId) {
        QueryWrapper<ClearingDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transit_order_id", transitOrderId);
        return clearingDetailMapper.selectOne(queryWrapper);
    }

    /**
     * 通过费率设置新的各项费用
     */
    @Override
    public ClearingDetail setClearingDetailCost(ClearingDetail clearingDetail) {
        //-货主手续费
        clearingDetail.setShipperFeeCost(MathUtil.multiply(clearingDetail.getShipperTransportCost(), clearingDetail.getShipperFeeRate(),2));
        clearingDetail.setShipperTaxCost(0D);
        if (!clearingDetail.getIncludedTax()) {
            Double transitTaxCost = MathUtil.multiply(clearingDetail.getShipperTransportCost(), clearingDetail.getShipperTaxRate(),2);
            clearingDetail.setShipperTaxCost(transitTaxCost);
        }
        //-真实含税运输费
        Double actualRateTransportCost = MathUtil.add(clearingDetail.getShipperTransportCost(), clearingDetail.getShipperTaxCost());
        //-计算运营服务费 1
//        clearingDetail.setPlatOperateFee(calculationService.calculateOperateFee(clearingDetail.getPlatId(), actualRateTransportCost));
//        //-计算运营服务费 2
//        clearingDetail.setZoneOperateFee(calculationService.calculateOperateFee(clearingDetail.getZonePlatId(), actualRateTransportCost));
        //最终支付给平台的费用
        clearingDetail.setShipperActualPayCost(MathUtil.add(actualRateTransportCost, clearingDetail.getShipperFeeCost()));
        clearingDetail.setTruckerFeeCost(MathUtil.multiply(clearingDetail.getShipperTransportCost(), clearingDetail.getTruckerFeeRate(),2));
        //运费含税，要从运费中扣除司机税费（不含税货主已额外支付）
        if (clearingDetail.getIncludedTax()) {
            Double addedTaxCost = MathUtil.multiply(clearingDetail.getShipperTransportCost(), clearingDetail.getAddedTaxRate(),2);
            clearingDetail.setAddedTaxCost(addedTaxCost);
            Double cityTaxCost = MathUtil.multiply(clearingDetail.getAddedTaxCost(), clearingDetail.getCityTaxRate(),2);
            clearingDetail.setCityTaxCost(cityTaxCost);
            Double localEduTaxCost = MathUtil.multiply(clearingDetail.getAddedTaxCost(), clearingDetail.getLocalEduTaxRate(),2);
            clearingDetail.setLocalEduTaxCost(localEduTaxCost);
            Double eduAddTaxCost = MathUtil.multiply(clearingDetail.getAddedTaxCost(), clearingDetail.getEduAddTaxRate(),2);
            clearingDetail.setEduAddTaxCost(eduAddTaxCost);
            Double incomeTaxCost = MathUtil.multiply(clearingDetail.getShipperTransportCost(), clearingDetail.getIncomeTaxRate(),2);
            clearingDetail.setIncomeTaxCost(incomeTaxCost);
            clearingDetail.setTruckerTaxCost(MathUtil.add(addedTaxCost, cityTaxCost, localEduTaxCost, eduAddTaxCost, incomeTaxCost));
        }

        //最终付款给司机的费用
        double truckerActualTheoryCost = MathUtil.subtract(clearingDetail.getShipperTransportCost(), clearingDetail.getTruckerFeeCost());
        truckerActualTheoryCost = MathUtil.subtract(truckerActualTheoryCost, clearingDetail.getOilCost(), clearingDetail.getEtcTollCost());
        truckerActualTheoryCost = MathUtil.subtract(truckerActualTheoryCost, clearingDetail.getDiffIndemnityCost(), clearingDetail.getTruckerTaxCost());
        truckerActualTheoryCost = MathUtil.add(truckerActualTheoryCost, clearingDetail.getAdditionalCost());
        //减去后才是最后实付费用
        clearingDetail.setTruckerActualTheoryCost(MathUtil.round(truckerActualTheoryCost, 2));
        /**
         * TODO: 危险区标记 2
         * 在清算后生成结款单时，就基本确认了司机的【提现】费用
         * 需要注意的是: 这里需要判断是否在汇总时就处理了司机此项费用
         * 如果未处理，这里要重新生成
         * */
        if (clearingDetail.getGatherRecordId()==null){
            double technicalFee = calculationService.calculateTechnicalFee(truckerActualTheoryCost);
            clearingDetail.setTechnicalFeeCost(MathUtil.round(technicalFee,2));
        }

        //-计算运营服务费 1
//        clearingDetail.setPlatTechnicalFee(calculationService.calculateOperateFee(clearingDetail.getPlatId(), clearingDetail.getTechnicalFeeCost()));
//        //-计算运营服务费 2
//        clearingDetail.setZoneTechnicalFee(calculationService.calculateOperateFee(clearingDetail.getZonePlatId(), clearingDetail.getTechnicalFeeCost()));

        clearingDetail.setTruckerActualIncomeCost(MathUtil.round(MathUtil.subtract(truckerActualTheoryCost,clearingDetail.getTechnicalFeeCost()),2));
        clearingDetail.setShipperActualPayCost(MathUtil.round(clearingDetail.getShipperTransportCost(), 2));
        return clearingDetail;
    }

    @Override
    public List<ClearingDetail> getClearingListByGatherId(String gatherRecordId) {
        QueryWrapper<ClearingDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("gather_record_id", gatherRecordId);
        return clearingDetailMapper.selectList(queryWrapper);
    }

}